##########################################
## Copyright 2012-2013 Ceruti Francesco & contributors
##
## This file is part of LiSP (Linux Show Player).
##########################################

from PyQt4 import QtGui, QtCore


class QLevelPlotter(QtGui.QWidget):

    DB_MIN = -40
    DB_MAX = 0

    STEP_SIZE = 5

    def __init__(self, parent):
        super(QLevelPlotter, self).__init__(parent)
        self.clipping = None
        self.reset()

    def reset(self):
        self.levels = [QLevelPlotter.DB_MIN, QLevelPlotter.DB_MIN]
        self.decPeak = [QLevelPlotter.DB_MIN, QLevelPlotter.DB_MIN]
        self.repaint()

    def plot(self, levels, decPeak):
        if(len(levels) == 1):
            self.plot(levels * 2, decPeak * 2)
        else:
            self.levels = decPeak
            for n in range(len(self.decPeak)):
                if(self.decPeak[n] < decPeak[n]):
                    self.decPeak[n] = decPeak[n]
            if(self.clipping is None):
                self.clipping = [False] * len(self.levels)
            self.repaint()

    def paintEvent(self, e):
        if(not self.visibleRegion().isEmpty()):
            # Stretch factor
            mul = (self.height() - 4) / (QLevelPlotter.DB_MAX - QLevelPlotter.DB_MIN)

            levels = []
            count = 0
            for level in self.levels:
                if(level > 0):
                    self.clipping[count] = True
                count += 1

                if(level < QLevelPlotter.DB_MIN):
                    level = QLevelPlotter.DB_MIN
                elif(level > QLevelPlotter.DB_MAX):
                    level = QLevelPlotter.DB_MAX
                levels.append(round((level - QLevelPlotter.DB_MIN) * mul))

            decPeaks = []
            for decPeak in self.decPeak:
                if(decPeak < QLevelPlotter.DB_MIN):
                    decPeak = QLevelPlotter.DB_MIN
                elif(decPeak > QLevelPlotter.DB_MAX):
                    decPeak = QLevelPlotter.DB_MAX
                decPeaks.append(round((decPeak - QLevelPlotter.DB_MIN) * mul))

            qp = QtGui.QPainter()
            qp.begin(self)
            qp.setBrush(QtGui.QColor(0, 0, 0, 0))

            xpos = 0
            xdim = self.width() / len(levels)

            grad = QtGui.QLinearGradient()
            grad.setColorAt(0, QtGui.QColor(0, 255, 0))         # Green
            grad.setColorAt(0.5, QtGui.QColor(255, 255, 0))     # Yellow
            grad.setColorAt(1, QtGui.QColor(255, 0, 0))         # Red

            for n in range(len(levels)):
                level = levels[n]
                decPeak = decPeaks[n]
                if(self.clipping != None):
                    if(len(self.clipping) < n):
                        self.clipping.append(False)
                    clipping = self.clipping[n]
                else:
                    clipping = False

                # Maximum "level-rect" size
                maxRect = QtCore.QRect(xpos, self.height() - 2, xdim - 2, 2 - self.height())

                # Set QLinearGradient start and final-stop position
                grad.setStart(maxRect.topLeft())
                grad.setFinalStop(maxRect.bottomRight())

                # Draw level (audio level in dB)
                rect = QtCore.QRect(xpos, self.height() - 2, xdim - 2, -level)
                qp.fillRect(rect, grad)

                # Draw decay peak
                decRect = QtCore.QRect(xpos, (self.height() - 3) - decPeak, xdim - 2, 2)
                qp.fillRect(decRect, grad)

                # Draw Borders
                if(clipping):
                    qp.setPen(QtGui.QColor(200, 0, 0))
                else:
                    qp.setPen(QtGui.QColor(100, 100, 100))
                qp.drawRect(maxRect)

                xpos += xdim

            qp.end()
